package com.iflytek.esb.service;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.iflytek.esb.domain.Message;
import com.iflytek.esb.domain.PersistenceMessage;
import com.iflytek.esb.exceptions.RetryableException;
import com.iflytek.esb.util.Consts;
import com.opensymphony.workflow.Workflow;
import com.opensymphony.workflow.WorkflowException;
import com.opensymphony.workflow.loader.WorkflowDescriptor;

@Service
public class WorkflowService {

	private static final Logger LOG = Logger.getLogger(WorkflowService.class);
	private static final int INIT_ACTION = 0;
	
	@Autowired
	private Workflow workflow;
	
	@Autowired
	private MessageService messageService;
	
	public String[] getWorkflowNames() {
		return workflow.getWorkflowNames();
	}
	
	public String getWorkflowName(long entryId) {
		if (entryId < 0) {
			return StringUtils.EMPTY;
		}
		return workflow.getWorkflowName(entryId);
	}
	
	@Transactional
	public long startWorkflow(PersistenceMessage message) throws WorkflowException {
		//得到服务名称
		String name = message.getHeaders().get(Consts.HEADER_SERVICE_NAME);
		
		//把消息放入容器让工作流处理
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(Consts.VAR_NAME_MESSAGE, message);
		
		//WorkflowDescriptor wd = null;
		
		//String actionName = StringUtils.EMPTY;
		//Exception x = null;
		long id = 0;
		try {
			//wd = workflow.getWorkflowDescriptor(name);
			//actionName = wd.getInitialAction(INIT_ACTION).getName();
			
			id = workflow.initialize(name, INIT_ACTION, map);
	
			//取出容器中的消息进行处理，先保存输入消息
			message.setEntryId(id);
			messageService.updateMessage(message);
			
//			//设置返回值
//			if (!StringUtils.isEmpty(response.getContent())) {
//				messageService.insertResponseMessage(
//						message.getId(), response.getHeaders(), response.getContent());
//			}
		}
		catch (RetryableException e) {
			//x = e;
			throw e;
		}
		catch (Exception e) {
			//x = e;
			throw new WorkflowException(e);
		}
		finally {
//			traceService.traceExecute(
//					id, name, INIT_ACTION, actionName, 
//					message.getHeaders(), message.getBody(), 
//					x != null, getExceptionMessage(x));
		}

		return id;
	}
	
	@Transactional
	public void executeWorkflow(long id, PersistenceMessage message) throws WorkflowException {
		
		//把消息放入容器让工作流处理
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(Consts.VAR_NAME_MESSAGE, message);
		
		//寻找需要执行的行为
		int[] actions = workflow.getAvailableActions(id, map);
		
		String workflowName = workflow.getWorkflowName(id);
		WorkflowDescriptor wd =  workflow.getWorkflowDescriptor(workflowName);
		
		//执行工作流
		for (int i = 0; i < actions.length; i ++) {
			
			//Exception x = null;
			String actionName = StringUtils.EMPTY;
			try {
				actionName = wd.getAction(actions[i]).getName();
				LOG.debug("execute action: " + actionName);
				
				//执行流程
				workflow.doAction(id, actions[i], map);
			}
			catch (RetryableException e) {
				//x = e;
				throw e;
			}
			catch (Exception e) {
				//x = e;
				throw new WorkflowException(e);
			}
			finally {
//				//保存消息跟踪记录
//				traceService.traceExecute(
//						id, workflowName, actions[i], actionName, 
//						message.getHeaders(), message.getBody(), 
//						x != null, getExceptionMessage(x));
			}
		}

		//先保存输入消息
		messageService.updateMessage(message);
		
//		设置返回值
//		if (!StringUtils.isEmpty(response.getBody())) {
//			messageService.insertResponseMessage(message.getId(), response.getHeaders(), response.getBody());
//		}
	}
	
	public int[] getAvailableActions(long id, Message message) {
		
		Map<String, Object> map = new HashMap<String, Object>();
		map.put(Consts.VAR_NAME_MESSAGE, message);
		
		return workflow.getAvailableActions(id, map);
	}

	public WorkflowDescriptor getWorkflowDescriptor(String name) {
		return workflow.getWorkflowDescriptor(name);
	}

//	private String getExceptionMessage(Exception e) {
//		if (e == null) {
//			return StringUtils.EMPTY;
//		}
//		StringWriter errors = new StringWriter();
//		e.printStackTrace(new PrintWriter(errors));
//		return e.getMessage() + "\r\n" + errors.toString();
//	}
}
